angular
  .module("ui.bootstrap.datepicker", [
    "ui.bootstrap.dateparser",
  ])

  .value("$datepickerSuppressError", false)

  .value("$datepickerLiteralWarning", true)

  .constant("uibDatepickerConfig", {
    datepickerMode: "day",
    formatDay: "dd",
    formatMonth: "MMMM",
    formatYear: "yyyy",
    formatDayHeader: "EEE",
    formatDayTitle: "MMM yyyy",
    formatMonthTitle: "yyyy",
    maxDate: null,
    maxMode: "year",
    minDate: null,
    minMode: "day",
    monthColumns: 3,
    ngModelOptions: {},
    shortcutPropagation: false,
    showWeeks: true,
    yearColumns: 5,
    yearRows: 4
  })

  .controller("UibDatepickerController", [
    "$scope",
    "$element",
    "$attrs",
    "$parse",
    "$interpolate",
    "$locale",
    "$log",
    "dateFilter",
    "uibDatepickerConfig",
    "$datepickerLiteralWarning",
    "$datepickerSuppressError",
    "uibDateParser",
    function (
      $scope,
      $element,
      $attrs,
      $parse,
      $interpolate,
      $locale,
      $log,
      dateFilter,
      datepickerConfig,
      $datepickerLiteralWarning,
      $datepickerSuppressError,
      dateParser
    ) {
      var self = this,
        ngModelCtrl = {
          $setViewValue: angular.noop
        }, // nullModelCtrl;
        setting = {
          range: $attrs.range == "true" ? true : false
        },
        ngModelOptions = {},
        watchListeners = [];
      $element.addClass("uib-datepicker");
      $attrs.$set("role", "application");

      if (!$scope.datepickerOptions) {
        $scope.datepickerOptions = {};
      }

      // Modes chain
      this.modes = ["day", "month", "year"];

      [
        "customClass",
        "dateDisabled",
        "datepickerMode",
        "formatDay",
        "formatDayHeader",
        "formatDayTitle",
        "formatMonth",
        "formatMonthTitle",
        "formatYear",
        "maxDate",
        "maxMode",
        "minDate",
        "minMode",
        "monthColumns",
        "showWeeks",
        "shortcutPropagation",
        "startingDay",
        "yearColumns",
        "yearRows"
      ].forEach(function (key) {
        switch (key) {
          case "customClass":
          case "dateDisabled":
            $scope[key] = $scope.datepickerOptions[key] || angular.noop;
            break;
          case "datepickerMode":
            $scope.datepickerMode = angular.isDefined(
                $scope.datepickerOptions.datepickerMode
              ) ?
              $scope.datepickerOptions.datepickerMode :
              datepickerConfig.datepickerMode;
            break;
          case "formatDay":
          case "formatDayHeader":
          case "formatDayTitle":
          case "formatMonth":
          case "formatMonthTitle":
          case "formatYear":
            self[key] = angular.isDefined($scope.datepickerOptions[key]) ?
              $interpolate($scope.datepickerOptions[key])($scope.$parent) :
              datepickerConfig[key];
            break;
          case "monthColumns":
          case "showWeeks":
          case "shortcutPropagation":
          case "yearColumns":
          case "yearRows":
            self[key] = angular.isDefined($scope.datepickerOptions[key]) ?
              $scope.datepickerOptions[key] :
              datepickerConfig[key];
            break;
          case "startingDay":
            if (angular.isDefined($scope.datepickerOptions.startingDay)) {
              self.startingDay = $scope.datepickerOptions.startingDay;
            } else if (angular.isNumber(datepickerConfig.startingDay)) {
              self.startingDay = datepickerConfig.startingDay;
            } else {
              self.startingDay =
                ($locale.DATETIME_FORMATS.FIRSTDAYOFWEEK + 8) % 7;
            }

            break;
          case "maxDate":
          case "minDate":
            $scope.$watch("datepickerOptions." + key, function (value) {
              if (value) {
                if (angular.isDate(value)) {
                  self[key] = dateParser.fromTimezone(
                    new Date(value),
                    ngModelOptions.getOption("timezone")
                  );
                } else {
                  if ($datepickerLiteralWarning) {
                    $log.warn(
                      "Literal date support has been deprecated, please switch to date object usage"
                    );
                  }

                  self[key] = new Date(dateFilter(value, "medium"));
                }
              } else {
                self[key] = datepickerConfig[key] ?
                  dateParser.fromTimezone(
                    new Date(datepickerConfig[key]),
                    ngModelOptions.getOption("timezone")
                  ) :
                  null;
              }

              self.refreshView();
            });

            break;
          case "maxMode":
          case "minMode":
            if ($scope.datepickerOptions[key]) {
              $scope.$watch(
                function () {
                  return $scope.datepickerOptions[key];
                },
                function (value) {
                  self[key] = $scope[key] = angular.isDefined(value) ?
                    value :
                    $scope.datepickerOptions[key];
                  if (
                    (key === "minMode" &&
                      self.modes.indexOf(
                        $scope.datepickerOptions.datepickerMode
                      ) < self.modes.indexOf(self[key])) ||
                    (key === "maxMode" &&
                      self.modes.indexOf(
                        $scope.datepickerOptions.datepickerMode
                      ) > self.modes.indexOf(self[key]))
                  ) {
                    $scope.datepickerMode = self[key];
                    $scope.datepickerOptions.datepickerMode = self[key];
                  }
                }
              );
            } else {
              self[key] = $scope[key] = datepickerConfig[key] || null;
            }

            break;
        }
      });

      $scope.uniqueId =
        "datepicker-" + $scope.$id + "-" + Math.floor(Math.random() * 10000);

      $scope.disabled = angular.isDefined($attrs.disabled) || false;
      if (angular.isDefined($attrs.ngDisabled)) {
        watchListeners.push(
          $scope.$parent.$watch($attrs.ngDisabled, function (disabled) {
            $scope.disabled = disabled;
            self.refreshView();
          })
        );
      }

      $scope.isActive = function (dateObject) {
        if (self.compare(dateObject.date, self.activeDate) === 0) {
          $scope.activeDateId = dateObject.uid;
          return true;
        }
        return false;
      };

      this.init = function (ngModelCtrl_) {
        ngModelCtrl = ngModelCtrl_;
        ngModelOptions = extractOptions(ngModelCtrl);

        if ($scope.datepickerOptions.initDate) {
          self.activeDate =
            dateParser.fromTimezone(
              $scope.datepickerOptions.initDate,
              ngModelOptions.getOption("timezone")
            ) || new Date();
          $scope.$watch("datepickerOptions.initDate", function (initDate) {
            if (
              initDate &&
              (ngModelCtrl.$isEmpty(ngModelCtrl.$modelValue) ||
                ngModelCtrl.$invalid)
            ) {
              self.activeDate = dateParser.fromTimezone(
                initDate,
                ngModelOptions.getOption("timezone")
              );
              self.refreshView();
            }
          });
        } else {
          self.activeDate = new Date();
        }

        var date = ngModelCtrl.$modelValue ?
          new Date(ngModelCtrl.$modelValue) :
          new Date();
        this.activeDate = !isNaN(date) ?
          dateParser.fromTimezone(date, ngModelOptions.getOption("timezone")) :
          dateParser.fromTimezone(
            new Date(),
            ngModelOptions.getOption("timezone")
          );

        ngModelCtrl.$render = function () {
          self.render();
        };
      };

      this.render = function () {
        if (setting.range) {} else {
          if (ngModelCtrl.$viewValue) {
            var date = new Date(ngModelCtrl.$viewValue),
              isValid = !isNaN(date);
            if (isValid) {
              this.activeDate = dateParser.fromTimezone(
                date,
                ngModelOptions.getOption("timezone")
              );
            } else if (!$datepickerSuppressError) {
              $log.error(
                'Datepicker directive: "ng-model" value must be a Date object'
              );
            }
          }
        }
        this.refreshView();
      };

      this.refreshView = function () {
        if (this.element) {
          if (setting.range) {
            this._refreshView();
          } else {
            $scope.selectedDt = null;
            this._refreshView();
            if ($scope.activeDt) {
              $scope.activeDateId = $scope.activeDt.uid;
            }
            var date = ngModelCtrl.$viewValue ?
              new Date(ngModelCtrl.$viewValue) :
              null;
            date = dateParser.fromTimezone(
              date,
              ngModelOptions.getOption("timezone")
            );
            ngModelCtrl.$setValidity(
              "dateDisabled",
              !date || (this.element && !this.isDisabled(date))
            );
          }
        }
      };
      this.tdPosition = function (date) {
        if (setting.range) {
          var startModel = this.setDate(ngModelCtrl.$viewValue.startTime);
          var endModel = this.setDate(ngModelCtrl.$viewValue.endTime);
          startModel = dateParser.fromTimezone(startModel, ngModelOptions.getOption("timezone"));
          endModel = dateParser.fromTimezone(endModel, ngModelOptions.getOption("timezone"));
          if (this.compare(date, startModel) == 0) {
            return 'start';
          } else if (this.compare(date, endModel) == 0) {
            return 'end';
          } else if (date > startModel && date < endModel) {
            return 'middle';
          }
          return false;
        } else {
          var model = this.setDate(ngModelCtrl.$viewValue);
          model = dateParser.fromTimezone(model, ngModelOptions.getOption("timezone"));
          return model && this.compare(date, model) === 0 ? true : false;
        }

      };
      this.createDateObject = function (date, format) {
        var tdPosition = this.tdPosition(date);
        var selected = tdPosition ? true : false;
        var today = new Date();
        today = dateParser.fromTimezone(
          today,
          ngModelOptions.getOption("timezone")
        );
        var time = this.compare(date, today);
        var dt = {
          date: date,
          label: dateParser.filter(date, format),
          selected: selected,
          disabled: this.isDisabled(date),
          position: tdPosition,
          past: time < 0,
          current: time === 0,
          future: time > 0,
          customClass: this.customClass(date) || null
        };
        return dt;
      };
      this.isDisabled = function (date) {
        return (
          $scope.disabled ||
          (this.minDate && this.compare(date, this.minDate) < 0) ||
          (this.maxDate && this.compare(date, this.maxDate) > 0) ||
          ($scope.dateDisabled &&
            $scope.dateDisabled({
              date: date,
              mode: $scope.datepickerMode,
              currentMonth: this.activeDate.getMonth()
            }))
        );
      };

      this.customClass = function (date) {
        return $scope.customClass({
          date: date,
          mode: $scope.datepickerMode,
          currentMonth: this.activeDate.getMonth()
        });
      };
      this.setDate = function (date) {
        return date ? new Date(date) : null;
      };
      // Split array into smaller arrays
      this.split = function (arr, size) {
        var arrays = [];
        while (arr.length > 0) {
          arrays.push(arr.splice(0, size));
        }
        return arrays;
      };

      $scope.select = function (date) {
        if ($scope.datepickerMode === self.minMode) {
          if (setting.range) {
            var dt = new Date(0, 0, 0, 0, 0, 0, 0);
            dt.setFullYear(date.getFullYear(), date.getMonth(), date.getDate());
            dt = dateParser.toTimezone(dt, ngModelOptions.getOption("timezone"));
            if (ngModelCtrl.$viewValue.startTime) {
              if (ngModelCtrl.$viewValue.endTime) {
                ngModelCtrl.$viewValue.startTime = dt;
                ngModelCtrl.$viewValue.endTime = null;
              } else {
                if (dt > ngModelCtrl.$viewValue.startTime) {
                  ngModelCtrl.$viewValue.endTime = dt;
                } else {
                  ngModelCtrl.$viewValue.endTime = ngModelCtrl.$viewValue.startTime;
                  ngModelCtrl.$viewValue.startTime = dt;
                }
              }
            } else {
              ngModelCtrl.$viewValue.startTime = dt;
            }
          } else {
            var dt = ngModelCtrl.$viewValue ?
              dateParser.fromTimezone(
                new Date(ngModelCtrl.$viewValue),
                ngModelOptions.getOption("timezone")
              ) :
              new Date(0, 0, 0, 0, 0, 0, 0);
            dt.setFullYear(date.getFullYear(), date.getMonth(), date.getDate());
            dt = dateParser.toTimezone(
              dt,
              ngModelOptions.getOption("timezone")
            );
            ngModelCtrl.$setViewValue(dt);
          }
          ngModelCtrl.$render();
        } else {
          self.activeDate = date;
          setMode(self.modes[self.modes.indexOf($scope.datepickerMode) - 1]);
          $scope.$emit("uib:datepicker.mode");
        }

        $scope.$broadcast("uib:datepicker.focus");
      };

      $scope.move = function (direction) {
        var year =
          self.activeDate.getFullYear() + direction * (self.step.years || 0),
          month =
          self.activeDate.getMonth() + direction * (self.step.months || 0);
        self.activeDate.setFullYear(year, month, 1);
        self.refreshView();
      };

      $scope.toggleMode = function (direction) {
        direction = direction || 1;

        if (
          ($scope.datepickerMode === self.maxMode && direction === 1) ||
          ($scope.datepickerMode === self.minMode && direction === -1)
        ) {
          return;
        }

        setMode(
          self.modes[self.modes.indexOf($scope.datepickerMode) + direction]
        );

        $scope.$emit("uib:datepicker.mode");
      };

      // Key event mapper
      $scope.keys = {
        13: "enter",
        32: "space",
        33: "pageup",
        34: "pagedown",
        35: "end",
        36: "home",
        37: "left",
        38: "up",
        39: "right",
        40: "down"
      };

      var focusElement = function () {
        self.element[0].focus();
      };

      // Listen for focus requests from popup directive
      $scope.$on("uib:datepicker.focus", focusElement);
      $scope.keydown = function (evt) {
        var key = $scope.keys[evt.which];

        if (!key || evt.shiftKey || evt.altKey || $scope.disabled) {
          return;
        }

        evt.preventDefault();
        if (!self.shortcutPropagation) {
          evt.stopPropagation();
        }

        if (key === "enter" || key === "space") {
          if (self.isDisabled(self.activeDate)) {
            return; // do nothing
          }
          $scope.select(self.activeDate);
        } else if (evt.ctrlKey && (key === "up" || key === "down")) {
          $scope.toggleMode(key === "up" ? 1 : -1);
        } else {
          self.handleKeyDown(key, evt);
          self.refreshView();
        }
      };

      $element.on("keydown", function (evt) {
        $scope.$apply(function () {
          $scope.keydown(evt);
        });
      });

      $scope.$on("$destroy", function () {
        //Clear all watch listeners on destroy
        while (watchListeners.length) {
          watchListeners.shift()();
        }
      });

      function setMode(mode) {
        $scope.datepickerMode = mode;
        $scope.datepickerOptions.datepickerMode = mode;
      }

      function extractOptions(ngModelCtrl) {
        var ngModelOptions;

        if (angular.version.minor < 6) {
          // in angular < 1.6 $options could be missing
          // guarantee a value
          ngModelOptions =
            ngModelCtrl.$options ||
            $scope.datepickerOptions.ngModelOptions ||
            datepickerConfig.ngModelOptions || {};

          // mimic 1.6+ api
          ngModelOptions.getOption = function (key) {
            return ngModelOptions[key];
          };
        } else {
          // in angular >=1.6 $options is always present
          // ng-model-options defaults timezone to null; don't let its precedence squash a non-null value
          var timezone =
            ngModelCtrl.$options.getOption("timezone") ||
            ($scope.datepickerOptions.ngModelOptions ?
              $scope.datepickerOptions.ngModelOptions.timezone :
              null) ||
            (datepickerConfig.ngModelOptions ?
              datepickerConfig.ngModelOptions.timezone :
              null);

          // values passed to createChild override existing values
          ngModelOptions = ngModelCtrl.$options // start with a ModelOptions instance
            .createChild(datepickerConfig.ngModelOptions) // lowest precedence
            .createChild($scope.datepickerOptions.ngModelOptions)
            .createChild(ngModelCtrl.$options) // highest precedence
            .createChild({
              timezone: timezone
            }); // to keep from squashing a non-null value
        }

        return ngModelOptions;
      }
    }
  ])

  .controller("UibDaypickerController", [
    "$scope",
    "$element",
    "dateFilter",
    function (scope, $element, dateFilter) {
      var DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
      this.step = {
        months: 1
      };
      this.element = $element;

      function getDaysInMonth(year, month) {
        return month === 1 &&
          year % 4 === 0 &&
          (year % 100 !== 0 || year % 400 === 0) ?
          29 :
          DAYS_IN_MONTH[month];
      }

      this.init = function (ctrl) {
        angular.extend(ctrl, this);
        scope.showWeeks = ctrl.showWeeks;
        ctrl.refreshView();
      };

      this.getDates = function (startDate, n) {
        var dates = new Array(n),
          current = new Date(startDate),
          i = 0,
          date;
        while (i < n) {
          date = new Date(current);
          dates[i++] = date;
          current.setDate(current.getDate() + 1);
        }
        return dates;
      };

      this._refreshView = function () {
        var year = this.activeDate.getFullYear(),
          month = this.activeDate.getMonth(),
          firstDayOfMonth = new Date(this.activeDate);

        firstDayOfMonth.setFullYear(year, month, 1);

        var difference = this.startingDay - firstDayOfMonth.getDay(),
          numDisplayedFromPreviousMonth =
          difference > 0 ? 7 - difference : -difference,
          firstDate = new Date(firstDayOfMonth);

        if (numDisplayedFromPreviousMonth > 0) {
          firstDate.setDate(-numDisplayedFromPreviousMonth + 1);
        }

        // 42 is the number of days on a six-week calendar
        var days = this.getDates(firstDate, 42);
        for (var i = 0; i < 42; i++) {
          days[i] = angular.extend(
            this.createDateObject(days[i], this.formatDay), {
              secondary: days[i].getMonth() !== month,
              uid: scope.uniqueId + "-" + i
            }
          );
        }

        scope.labels = new Array(7);
        for (var j = 0; j < 7; j++) {
          scope.labels[j] = {
            abbr: dateFilter(days[j].date, this.formatDayHeader),
            full: dateFilter(days[j].date, "EEEE")
          };
        }

        scope.title = dateFilter(this.activeDate, this.formatDayTitle);
        scope.rows = this.split(days, 7);
        if (scope.showWeeks) {
          scope.weekNumbers = [];
          var thursdayIndex = (4 + 7 - this.startingDay) % 7,
            numWeeks = scope.rows.length;
          for (var curWeek = 0; curWeek < numWeeks; curWeek++) {
            scope.weekNumbers.push(
              getISO8601WeekNumber(scope.rows[curWeek][thursdayIndex].date)
            );
          }
        }
      };

      this.compare = function (date1, date2) {
        var _date1 = date1;
        var _date2 = date2;
        if (date1) {
          _date1 = new Date(
            date1.getFullYear(),
            date1.getMonth(),
            date1.getDate()
          );
          _date1.setFullYear(date1.getFullYear());
        }
        if (date2) {
          _date2 = new Date(
            date2.getFullYear(),
            date2.getMonth(),
            date2.getDate()
          );
          _date2.setFullYear(date2.getFullYear());
        }
        return _date1 - _date2;
      };

      function getISO8601WeekNumber(date) {
        var checkDate = new Date(date);
        checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); // Thursday
        var time = checkDate.getTime();
        checkDate.setMonth(0); // Compare with Jan 1
        checkDate.setDate(1);
        return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
      }

      this.handleKeyDown = function (key, evt) {
        var date = this.activeDate.getDate();

        if (key === "left") {
          date = date - 1;
        } else if (key === "up") {
          date = date - 7;
        } else if (key === "right") {
          date = date + 1;
        } else if (key === "down") {
          date = date + 7;
        } else if (key === "pageup" || key === "pagedown") {
          var month = this.activeDate.getMonth() + (key === "pageup" ? -1 : 1);
          this.activeDate.setMonth(month, 1);
          date = Math.min(
            getDaysInMonth(
              this.activeDate.getFullYear(),
              this.activeDate.getMonth()
            ),
            date
          );
        } else if (key === "home") {
          date = 1;
        } else if (key === "end") {
          date = getDaysInMonth(
            this.activeDate.getFullYear(),
            this.activeDate.getMonth()
          );
        }
        this.activeDate.setDate(date);
      };
    }
  ])

  .controller("UibMonthpickerController", [
    "$scope",
    "$element",
    "dateFilter",
    function (scope, $element, dateFilter) {
      this.step = {
        years: 1
      };
      this.element = $element;

      this.init = function (ctrl) {
        angular.extend(ctrl, this);
        ctrl.refreshView();
      };

      this._refreshView = function () {
        var months = new Array(12),
          year = this.activeDate.getFullYear(),
          date;

        for (var i = 0; i < 12; i++) {
          date = new Date(this.activeDate);
          date.setFullYear(year, i, 1);
          months[i] = angular.extend(
            this.createDateObject(date, this.formatMonth), {
              uid: scope.uniqueId + "-" + i
            }
          );
        }

        scope.title = dateFilter(this.activeDate, this.formatMonthTitle);
        scope.rows = this.split(months, this.monthColumns);
        scope.yearHeaderColspan =
          this.monthColumns > 3 ? this.monthColumns - 2 : 1;
      };

      this.compare = function (date1, date2) {
        var _date1 = date1;
        if (date1) {
          date1 = new Date(date1.getFullYear(), date1.getMonth());
          _date1.setFullYear(date1.getFullYear());
        }
        var _date2 = date2;
        if (date2) {
          _date2 = new Date(date2.getFullYear(), date2.getMonth());
          _date2.setFullYear(date2.getFullYear());
        }
        return _date1 - _date2;
      };

      this.handleKeyDown = function (key, evt) {
        var date = this.activeDate.getMonth();

        if (key === "left") {
          date = date - 1;
        } else if (key === "up") {
          date = date - this.monthColumns;
        } else if (key === "right") {
          date = date + 1;
        } else if (key === "down") {
          date = date + this.monthColumns;
        } else if (key === "pageup" || key === "pagedown") {
          var year =
            this.activeDate.getFullYear() + (key === "pageup" ? -1 : 1);
          this.activeDate.setFullYear(year);
        } else if (key === "home") {
          date = 0;
        } else if (key === "end") {
          date = 11;
        }
        this.activeDate.setMonth(date);
      };
    }
  ])

  .controller("UibYearpickerController", [
    "$scope",
    "$element",
    "dateFilter",
    function (scope, $element, dateFilter) {
      var columns, range;
      this.element = $element;

      function getStartingYear(year) {
        return parseInt((year - 1) / range, 10) * range + 1;
      }

      this.yearpickerInit = function () {
        columns = this.yearColumns;
        range = this.yearRows * columns;
        this.step = {
          years: range
        };
      };

      this._refreshView = function () {
        var years = new Array(range),
          date;

        for (var i = 0, start = getStartingYear(this.activeDate.getFullYear()); i < range; i++) {
          date = new Date(this.activeDate);
          date.setFullYear(start + i, 0, 1);
          years[i] = angular.extend(
            this.createDateObject(date, this.formatYear), {
              uid: scope.uniqueId + "-" + i
            }
          );
        }
        scope.title = [years[0].date.getFullYear(), years[range - 1].date.getFullYear()].join(" - ");
        scope.rows = this.split(years, columns);
        scope.columns = columns;
      };
      this.compare = function (date1, date2) {
        if (date1 && date2) {
          return date1.getFullYear() - date2.getFullYear();
        } else {
          return false;
        }
      };

      this.handleKeyDown = function (key, evt) {
        var date = this.activeDate.getFullYear();

        if (key === "left") {
          date = date - 1;
        } else if (key === "up") {
          date = date - columns;
        } else if (key === "right") {
          date = date + 1;
        } else if (key === "down") {
          date = date + columns;
        } else if (key === "pageup" || key === "pagedown") {
          date += (key === "pageup" ? -1 : 1) * range;
        } else if (key === "home") {
          date = getStartingYear(this.activeDate.getFullYear());
        } else if (key === "end") {
          date = getStartingYear(this.activeDate.getFullYear()) + range - 1;
        }
        this.activeDate.setFullYear(date);
      };
    }
  ])

  .directive("uibDatepicker", function () {
    return {
      templateUrl: function (element, attrs) {
        return (
          attrs.templateUrl ||
          "./libs/datepicker/html/datepicker/datepicker.html"
        );
      },
      scope: {
        datepickerOptions: "=?"
      },
      require: ["uibDatepicker", "^ngModel"],
      restrict: "A",
      controller: "UibDatepickerController",
      controllerAs: "datepicker",
      link: function (scope, element, attrs, ctrls) {
        var datepickerCtrl = ctrls[0],
          ngModelCtrl = ctrls[1];
        scope.$on('$RESET_DATEPICKER', function () {
          datepickerCtrl.init(ngModelCtrl);
        })
        datepickerCtrl.init(ngModelCtrl);
      }
    };
  })

  .directive("uibDaypicker", function () {
    return {
      templateUrl: function (element, attrs) {
        return (
          attrs.templateUrl || "./libs/datepicker/html/datepicker/day.html"
        );
      },
      require: ["^uibDatepicker", "uibDaypicker"],
      restrict: "A",
      controller: "UibDaypickerController",
      link: function (scope, element, attrs, ctrls) {
        var datepickerCtrl = ctrls[0],
          daypickerCtrl = ctrls[1];

        daypickerCtrl.init(datepickerCtrl);
      }
    };
  })

  .directive("uibMonthpicker", function () {
    return {
      templateUrl: function (element, attrs) {
        return (
          attrs.templateUrl || "./libs/datepicker/html/datepicker/month.html"
        );
      },
      require: ["^uibDatepicker", "uibMonthpicker"],
      restrict: "A",
      controller: "UibMonthpickerController",
      link: function (scope, element, attrs, ctrls) {
        var datepickerCtrl = ctrls[0],
          monthpickerCtrl = ctrls[1];

        monthpickerCtrl.init(datepickerCtrl);
      }
    };
  })

  .directive("uibYearpicker", function () {
    return {
      templateUrl: function (element, attrs) {
        return (
          attrs.templateUrl || "./libs/datepicker/html/datepicker/year.html"
        );
      },
      require: ["^uibDatepicker", "uibYearpicker"],
      restrict: "A",
      controller: "UibYearpickerController",
      link: function (scope, element, attrs, ctrls) {
        var ctrl = ctrls[0];
        angular.extend(ctrl, ctrls[1]);
        ctrl.yearpickerInit();

        ctrl.refreshView();
      }
    };
  });